package gen

import (
	"gitee.com/zhuliangcai/knife/timeutil"
	"sync/atomic"
	"time"
)

// Snowflake 首位0，workid占有10位，时间戳41位，自增占用12位
// Snowflake 改进简化版雪花算法
type Snowflake struct {
	startId   int64
	wid       int64
	startTime int64
}

// NewSnowflake http://www.manongjc.com/detail/29-fixpagcswacgpvg.html
// NewSnowflake seata改进型雪花算法分布式ID-java实现
func NewSnowflake(workerId int64) *Snowflake {
	workerId &= 1023
	wid := workerId
	// 机器码左移至高位
	workerId <<= MachineBit
	st := time.Now().Unix()
	// 跟先前保存好的高11位进行一个或的位运算
	startId := workerId | (st << TimestampBit)
	return &Snowflake{startId, wid, st}
}

// NextId 获取唯一id
func (sf *Snowflake) NextId() int64 {
	return atomic.AddInt64(&sf.startId, 1)
}

func (sf *Snowflake) Info() (int64, int64, int64) {
	return explain(sf.startId)
}

func explain(id int64) (int64, int64, int64) {
	workerId := id >> MachineBit
	// 首位是0
	timestamp := (id << (WorkerBit + 1)) >> ((WorkerBit + 1) + TimestampBit)
	seq := id & 4095
	return workerId, timestamp, seq
}

func (sf *Snowflake) InfoString() (int64, string, int64) {
	workId, ts, seq := sf.Info()
	return workId, timeutil.TimeFormat(ts), seq
}

// MachineBit 机器码移位52
const MachineBit = 53

// WorkerBit 工作位数
const WorkerBit = 10

// TimestampBit 时间戳移位12
const TimestampBit = 12
